import Plyr from "plyr";
import Hls from "hls.js";
import TCPlayer from "tcplayer.js";
import "plyr/dist/plyr.css";
export interface PlayerOptions {
  videoElement: HTMLVideoElement;
  videoUrl: string;
  videoPoster?: string;
  showTime?: boolean;
  isPortrait?: boolean;
  onTimeUpdate?: (time: number) => void;
  onLoadingChange?: (loading: boolean) => void;
}

export interface PlayerInstance {
  play: () => void;
  pause: () => void;
  destroy: () => void;
  onFullscreenChange?: (callback: (isFullscreen: boolean) => void) => void;
}

export class PlayerFactory {
  static createPlayer(options: PlayerOptions): PlayerInstance {
    if (options.videoUrl.includes("webrtc://")) {
      return new TCPlayerWrapper(options);
    } else if (options.videoUrl.endsWith(".m3u8")) {
      return new HLSPlayerWrapper(options);
    } else {
      return new PlyrPlayerWrapper(options);
    }
  }
}

class TCPlayerWrapper implements PlayerInstance {
  private player: any;
  private hls: Hls | null = null;

  constructor(private options: PlayerOptions) {
    this.init();
  }

  private init() {
    this.options.onLoadingChange?.(true);
    this.player = TCPlayer(this.options.videoElement.id, {
      sources: [
        {
          src: this.options.videoUrl,
          type: "webrtc"
        }
      ],
      autoplay: false,
      poster: this.options.videoPoster,
      width: "100%",
      height: "100%",
      fakeFullscreen: true,
      controlBar: {
        volumePanel: true,
        fullscreenToggle: this.options.isPortrait ? false : true,
        playToggle: false
      }
    });

    this.player.on("playing", () => {
      this.options.onLoadingChange?.(false);
    });

    this.player.on("error", () => {
      this.options.onLoadingChange?.(true);
    });

    this.player.on("timeupdate", () => {
      const currentTime = this.player?.currentTime();
      if (typeof currentTime === "number") {
        this.options.onTimeUpdate?.(currentTime);
      }
    });
    this.player.fullscreen = this.fullscreen;
  }

  play() {
    this.player?.play();
  }

  pause() {
    this.player?.pause();
  }

  destroy() {
    this.player?.dispose();
  }

  onFullscreenChange(callback: (isFullscreen: boolean) => void) {
    this.player?.on("fullscreenchange", () => {
      const isFullscreen = this.player.isFullscreen();
      console.log(isFullscreen);

      callback(isFullscreen);
    });
  }

  get fullscreen() {
    return {
      toggle: () => {
        const isFullscreen = this.player.isFullscreen();
        if (isFullscreen) {
          this.player.exitFullscreen();
        } else {
          this.player.requestFullscreen();
        }
      },
      exit: () => {
        this.player.exitFullscreen();
      }
    };
  }
}

class HLSPlayerWrapper implements PlayerInstance {
  private player: Plyr | null = null;
  private hls: Hls | null = null;

  constructor(private options: PlayerOptions) {
    this.init();
  }

  private init() {
    // 检查是否是 iOS 设备
    const isIOS =
      /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream;

    // iOS 设备使用原生 HLS 支持
    if (isIOS) {
      // this.initNativePlayer();
      this.initHlsPlayer();
    } else if (Hls.isSupported()) {
      this.initHlsPlayer();
    } else {
      console.warn("HLS is not supported in this browser");
      this.initNativePlayer();
    }
  }

  private initNativePlayer() {
    const controls = ["play", "mute"];
    if (this.options.showTime) {
      controls.push("current-time");
    }
    if (!this.options.isPortrait) {
      controls.push("fullscreen");
    }

    this.player = new Plyr(this.options.videoElement, {
      controls,
      hideControls: false,
      clickToPlay: false,
      fullscreen: { enabled: true },
      invertTime: false
    });

    this.player.poster = this.options.videoPoster;

    this.options.videoElement.addEventListener("loadedmetadata", () => {
      this.options.onLoadingChange?.(false);
    });

    this.options.videoElement.addEventListener("error", () => {
      this.options.onLoadingChange?.(true);
    });

    this.player.on("timeupdate", () => {
      const currentTime = this.player?.currentTime;
      if (typeof currentTime === "number") {
        this.options.onTimeUpdate?.(currentTime);
      }
    });
  }

  private initHlsPlayer() {
    this.options.onLoadingChange?.(true);
    this.hls = new Hls({
      debug: import.meta.env.VITE_VIDEO_DEBUG == true
    });

    const controls = ["play", "mute"];
    if (this.options.showTime) {
      controls.push("current-time");
    }
    if (!this.options.isPortrait) {
      controls.push("fullscreen");
    }

    this.player = new Plyr(this.options.videoElement, {
      controls,
      hideControls: false,
      clickToPlay: false,
      fullscreen: { enabled: true },
      invertTime: false
    });

    this.player.poster = this.options.videoPoster;

    this.hls.loadSource(this.options.videoUrl);
    this.hls.attachMedia(this.options.videoElement);

    this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
      this.options.onLoadingChange?.(false);
      this.player?.play();
    });

    this.hls.on(Hls.Events.ERROR, (event, data) => {
      if (data.fatal) {
        switch (data.type) {
          case Hls.ErrorTypes.NETWORK_ERROR:
            this.hls?.startLoad();
            break;
          case Hls.ErrorTypes.MEDIA_ERROR:
            this.hls?.recoverMediaError();
            break;
          default:
            this.hls?.destroy();
            this.initNativePlayer(); // 如果 HLS.js 失败，回退到原生播放器
            break;
        }
      }
    });

    this.player.on("timeupdate", () => {
      const currentTime = this.player?.currentTime;
      if (typeof currentTime === "number") {
        this.options.onTimeUpdate?.(currentTime);
      }
    });
  }

  play() {
    this.player?.play();
  }

  pause() {
    this.player?.pause();
  }

  destroy() {
    this.player?.destroy();
    this.hls?.destroy();
  }

  onFullscreenChange(callback: (isFullscreen: boolean) => void) {
    this.player?.on("enterfullscreen", () => callback(true));
    this.player?.on("exitfullscreen", () => callback(false));
  }
}

class PlyrPlayerWrapper implements PlayerInstance {
  private player: Plyr | null = null;

  constructor(private options: PlayerOptions) {
    this.init();
  }

  private init() {
    const controls = ["play", "mute"];
    if (this.options.showTime) {
      controls.push("current-time");
    }
    if (!this.options.isPortrait) {
      controls.push("fullscreen");
    }

    this.player = new Plyr(this.options.videoElement, {
      controls,
      hideControls: false,
      clickToPlay: false,
      fullscreen: { enabled: true },
      invertTime: false
    });

    this.player.poster = this.options.videoPoster;

    this.player.on("timeupdate", () => {
      const currentTime = this.player?.currentTime;
      if (typeof currentTime === "number") {
        this.options.onTimeUpdate?.(currentTime);
      }
    });
  }

  play() {
    this.player?.play();
  }

  pause() {
    this.player?.pause();
  }

  destroy() {
    this.player?.destroy();
  }

  onFullscreenChange(callback: (isFullscreen: boolean) => void) {
    this.player?.on("enterfullscreen", () => callback(true));
    this.player?.on("exitfullscreen", () => callback(false));
  }
}
